import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';
import 'package:zhibao_flutter/util/check/regular.dart';
import 'package:zhibao_flutter/util/config/app_config.dart';
import 'package:zhibao_flutter/util/data/q1_data.dart';
import 'package:zhibao_flutter/util/func/log.dart';
import 'package:zhibao_flutter/util/http/env.dart';

class UploadOss {
  // oss设置的bucket的名字
  static String bucket = 'candy-circle-copy';

  /// 目录
  static String rootDir = 'image';

  /// 地区
  static String region = 'oss-cn-qingdao';

  // 完整例子：
  // https://candy-circle-copy.oss-cn-qingdao.aliyuncs.com/image/20221031/4d45ee4fd0a87d75099e781d5055c10b.png
  //
  // 发送请求的url,根据你自己设置的是哪个城市的
  static String url = 'https://$bucket.$region.aliyuncs.com';

  // 过期时间
  static String expiration = '2025-01-01T12:00:00.000Z';

  static String getPathName(File file) {
    return '$rootDir/${getDate()}/${getRandom(32)}.${getFileType(file.path)}';
  }

  /**
   * @params file 要上传的文件对象
   * @params rootDir 阿里云oss设置的根目录文件夹名字
   * @param callback 回调函数我这里用于传cancelToken，方便后期关闭请求
   * @param onSendProgress 上传的进度事件
   */

  static Future<String> upload(
      {required String ossAccessKeyId,
      required String ossAccessKeySecret,
      required File file,
      required String pathName,
      Function? callback,
      ProgressCallback? onSendProgress}) async {
    String policyText =
        '{"expiration": "$expiration","conditions": [{"bucket": "$bucket" },["content-length-range", 0, 1048576000]]}';

    // 获取签名
    String signature = getSignature(ossAccessKeySecret, policyText);

    BaseOptions options = BaseOptions();
    options.responseType = ResponseType.plain;

    //创建dio对象
    Dio dio = Dio(options);
    // 生成oss的路径和文件名我这里目前设置的是image/20201229/test.mp4

    LogUtil.d("实际传递给oss接口的pathName::$pathName");

    // 请求参数的form对象
    FormData data = FormData.fromMap({
      'key': pathName,
      'policy': getSplicyBase64(policyText),
      'OSSAccessKeyId': ossAccessKeyId,
      'success_action_status': '200', //让服务端返回200，不然，默认会返回204
      'signature': signature,
      'contentType': 'multipart/form-data',
      'file': MultipartFile.fromFileSync(file.path),
    });

    print("FormData.fromMap::data::${data.fields}");

    Response response;
    CancelToken uploadCancelToken = CancelToken();
    if (callback != null) callback(uploadCancelToken);

    try {
      // 发送请求
      response = await dio.post(url, data: data, cancelToken: uploadCancelToken,
          onSendProgress: (int count, int data) {
        if (onSendProgress != null) onSendProgress(count, data);
        print("onSendProgress::count:$count, data:$data");
      });
      // 成功后返回文件访问路径
      return '$url/$pathName';
    } catch (e) {
      throw (e);
    }
  }

  /*
  * 生成固定长度的随机字符串
  * */
  static String getRandom(int num) {
    String alphabet = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM';
    String left = '';
    for (var i = 0; i < num; i++) {
//    right = right + (min + (Random().nextInt(max - min))).toString();
      left = left + alphabet[Random().nextInt(alphabet.length)];
    }
    return left;
  }

  /*
  * 根据图片本地路径获取图片名称
  * */
  static String getImageNameByPath(String? filePath) {
    // ignore: null_aware_before_operator
    return filePath?.substring(
            filePath.lastIndexOf("/") + 1, filePath.length) ??
        "";
  }

  /**
   * 获取文件类型
   */
  static String getFileType(String path) {
    print(path);
    List<String> array = path.split('.');
    return array[array.length - 1];
  }

  /// 获取日期
  static String getDate() {
    DateTime now = DateTime.now();
    return '${now.year}${now.month}${now.day}';
  }

  // 获取plice的base64
  static getSplicyBase64(String policyText) {
    //进行utf8编码
    List<int> policyText_utf8 = utf8.encode(policyText);
    //进行base64编码
    String policy_base64 = base64.encode(policyText_utf8);
    return policy_base64;
  }

  /// 获取签名
  static String getSignature(String ossAccessKeySecret, String policyText) {
    //进行utf8编码
    List<int> policyTextUtf8 = utf8.encode(policyText);
    //进行base64编码
    String policyBase64 = base64.encode(policyTextUtf8);
    //再次进行utf8编码
    List<int> policy = utf8.encode(policyBase64);
    //进行utf8 编码
    List<int> key = utf8.encode(ossAccessKeySecret);
    //通过hmac,使用sha1进行加密
    List<int> signaturePre = Hmac(sha1, key).convert(policy).bytes;
    //最后一步，将上述所得进行base64 编码
    String signature = base64.encode(signaturePre);
    return signature;
  }
}

// class UploadAvatar {
//   // 发送请求的url,根据你自己设置的是哪个城市的
//   static String url = '${Environment.current}/user/uploadAvatar';
//
//   static Future<String?> upload(
//       {required File file,
//       Function? callback,
//       ProgressCallback? onSendProgress}) async {
//     BaseOptions options = BaseOptions();
//
//     String? tokenStr = Q1Data.loginRspEntity?.token;
//     String tokenHead = AppConfig.tokenHead;
//     if (strNoEmpty(tokenStr)) {
//       options.headers[tokenHead] = tokenStr ?? '';
//     }
//     options.headers['Content-Type'] = "application/octet-stream";
//
//     //创建dio对象
//     Dio dio = Dio(options);
//     // 生成oss的路径和文件名我这里目前设置的是image/20201229/test.mp4
//
//     LogUtil.d("When `UploadAvatar` the file.path is ${file.path}");
//     // 请求参数的form对象
//     var data = FormData.fromMap({
//       'file': MultipartFile.fromFileSync(file.path),
//     });
//
//     print("FormData.fromMap::data::${data.fields}");
//     Response response;
//     CancelToken uploadCancelToken = CancelToken();
//     if (callback != null) callback(uploadCancelToken);
//
//     try {
//       // 发送请求
//       response = await dio.post(url, data: data, cancelToken: uploadCancelToken,
//           onSendProgress: (int count, int data) {
//         if (onSendProgress != null) onSendProgress(count, data);
//         print("onSendProgress::count:$count, data:$data");
//       });
//       if (response.statusCode == 401 ||
//           (response.data is Map &&
//               Map.from(response.data).containsKey('code') &&
//               Map.from(response.data)['code'] == 401)) {
//         return null;
//       }
//       // 成功后返回文件访问路径
//       return '${response.data}';
//     } catch (e) {
//       throw (e);
//     }
//   }
// }
